API Corner - Drive Informaition

© 2003, Brad Moore

author website:

LB Connection

Home

Tip Corner

Plot 3d

Memory Mapped File

Random File Selector

Notes for Beginners

No SoundBlaster Board

PrintInstalled Fonts

Essential Libby

API Drive Info

Begginer Series 6

Newsletter help

Index

Drive Informaition

I was working with drives the other day, and wondering about the UNC (Universal Named Connection) description of my drives. I usually have several of them mapped at any one time, and was trying to display their mappings in one of my projects. A little search revealed a neat little call that is part of the more obscure Windows library of mpr.dll. The call was WNetGetConnection. I could find very little information about it anywhere - and to my amazement, it was not one that Alyce seemed to have worked out yet.

I began to do a little searching around and found more than I needed right away on the AllAPI Network. The AllAPI Network has recently moved and is hosted in its static form at: [http://www.mentalis.org/index2.shtml]

The website not only contained valuable data, but also a great example program written in Visual Basic. The VB example used a couple other more common API calls to discover the various drive data for the computer it was being run on. These are GetDriveType and GetLogicalDriveStrings. I was able to get a neatly encapsulated function for GetDriveType from Alyce's awesome API32 library - which is part of Liberty Basic Workshop. I was forced to work out my own functions for the other two calls.

Here are the API definitions courtesy of the AllAPI Network [http://www.mentalis.org/index2.shtml]:

WNetGetConnection

The WNetGetConnection function retrieves the name of the network resource associated with a local device.

VB4-32,5,6

Private Declare Function WNetGetConnection Lib "mpr.dll" Alias "WNetGetConnectionA" (ByVal lpszLocalName As String, ByVal lpszRemoteName As String, cbRemoteName As Long) As Long

Operating Systems Supported

Library: Mpr

Parameter Information:

lpLocalName

(in) Pointer to a constant null-terminated string that specifies the name of the local device to get the network name for.

lpRemoteName

(out) Pointer to a buffer that receives the null-terminated remote name used to make the connection.

lpnLength

(in/out) Pointer to a variable that specifies the size, in characters, of the buffer pointed to by the lpRemoteName parameter. If the function fails because the buffer is not large enough, this parameter returns the required buffer size.

Return Values

If the function succeeds, the return value is NO_ERROR.

If the function fails, the return value is a system error code, such as one of the following values.

  • ERROR_BAD_DEVICE - The string pointed to by the lpLocalName parameter is invalid.
  • ERROR_NOT_CONNECTED - The device specified by lpLocalName is not a redirected device. For more information, see the following Remarks section.
  • ERROR_MORE_DATA - The buffer is too small. The lpnLength parameter points to a variable that contains the required buffer size. More entries are available with subsequent calls.
  • ERROR_CONNECTION_UNAVAIL - The device is not currently connected, but it is a persistent connection. For more information, see the following Remarks section.
  • ERROR_NO_NETWORK - The network is unavailable.
  • ERROR_EXTENDED_ERROR - A network-specific error occurred. To obtain a description of the error, call the WNetGetLastError function.
  • ERROR_NO_NET_OR_BAD_PATH - None of the providers recognize the local name as having a connection. However, the network is not available for at least one provider to whom the connection may belong.

GetDriveType

The GetDriveType function determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive.

VB4-32,5,6

Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long

Operating Systems Supported

Library: Kernel32

Parameter Information

lpRootPathName

Points to a null-terminated string that specifies the root directory of the disk to return information about. If lpRootPathName is NULL, the function uses the root of the current directory.

Return Values

  • The return value specifies the type of drive. It can be one of the following values:
  • DRIVE_UNKNOWN - The drive type cannot be determined.
  • DRIVE_NO_ROOT_DIR - The root directory does not exist.
  • DRIVE_REMOVABLE - The disk can be removed from the drive.
  • DRIVE_FIXED - The disk cannot be removed from the drive.
  • DRIVE_REMOTE - The drive is a remote (network) drive.
  • DRIVE_CDROM - The drive is a CD-ROM drive.
  • DRIVE_RAMDISK - The drive is a RAM disk.

GetLogicalDriveStrings

The GetLogicalDriveStrings function fills a buffer with strings that specify valid drives in the system.

VB4-32,5,6

Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogicalDriveStringsA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long

Operating Systems Supported

Library: Kernel32

Parameter Information

nBufferLength

Specifies the maximum size, in characters, of the buffer pointed to by lpBuffer. This size does not include the terminating null character.

lpBuffer

Points to a buffer that receives a series of null-terminated strings, one for each valid drive in the system, that end with a second null character. The following example shows the buffer contents with [null] representing the terminating null character.

c:\[null]d:\[null][null]

Return Values

If the function succeeds, the return value is the length, in characters, of the strings copied to the buffer, not including the terminating null character. Note that an ANSI-ASCII null character uses one byte, but a Unicode null character uses two bytes.

If the buffer is not large enough, the return value is greater than nBufferLength. It is the size of the buffer required to hold the drive strings.

If the function fails, the return value is zero. To get extended error information, use the GetLastError function.

As I mentioned, one of the three API calls were in Alyce's Win32 API wrapper functions for liberty basic. It was the GetDriveType. It is presented here:

Function GetDriveType(dir$)
    'print GetDriveType("c:\")
    CallDLL #kernel32, "GetDriveTypeA",dir$ As Ptr,GetDriveType As Long
    ' dType = 0 (No Drive)
    ' dType = 1 (Unknown Drive Type)
    ' dType = 2 (Floppy Drive)
    ' dType = 3 (Hard Drive)
    ' dType = 4 (Remote Drive)
    ' dType = 5 (CDROM)
    ' dType = 6 (RAMDISK)
    End Function

The key to the project however was the VB Program that was submitted to the AllAPI Network by Alexey (alexeyka2001@rambler.ru). It demonstrates all three of these API calls in use and gathers the actual UNC path of any mapped network drives. Here is the original VB program which I ported to LB

'Example by Alexey 
Private Const DRIVE_UNKNOWN = 0
Private Const DRIVE_ABSENT = 1
Private Const DRIVE_REMOVABLE = 2
Private Const DRIVE_FIXED = 3
Private Const DRIVE_REMOTE = 4
Private Const DRIVE_CDROM = 5
Private Const DRIVE_RAMDISK = 6
' returns errors for UNC Path
Private Const ERROR_BAD_DEVICE = 1200&
Private Const ERROR_CONNECTION_UNAVAIL = 1201&
Private Const ERROR_EXTENDED_ERROR = 1208&
Private Const ERROR_MORE_DATA = 234
Private Const ERROR_NOT_SUPPORTED = 50&
Private Const ERROR_NO_NET_OR_BAD_PATH = 1203&
Private Const ERROR_NO_NETWORK = 1222&
Private Const ERROR_NOT_CONNECTED = 2250&
Private Const NO_ERROR = 0


Private Declare Function WNetGetConnection Lib "mpr.dll" Alias _
        "WNetGetConnectionA" (ByVal lpszLocalName As String, _
        ByVal lpszRemoteName As String, cbRemoteName As Long) As Long
Private Declare Function GetLogicalDriveStrings Lib "kernel32" Alias _
    "GetLogicalDriveStringsA" (ByVal nBufferLength As Long, _
    ByVal lpBuffer As String) As Long
Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" _
    (ByVal nDrive As String) As Long
Private Function fGetDrives() As String
'Returns all mapped drives
    Dim lngRet As Long
    Dim strDrives As String * 255
    Dim lngTmp As Long
    lngTmp = Len(strDrives)
    lngRet = GetLogicalDriveStrings(lngTmp, strDrives)
    fGetDrives = Left(strDrives, lngRet)
End Function
Private Function fGetUNCPath(strDriveLetter As String) As String
    On Local Error GoTo fGetUNCPath_Err


    Dim Msg As String, lngReturn As Long
    Dim lpszLocalName As String
    Dim lpszRemoteName As String
    Dim cbRemoteName As Long
    lpszLocalName = strDriveLetter
    lpszRemoteName = String$(255, Chr$(32))
    cbRemoteName = Len(lpszRemoteName)
    lngReturn = WNetGetConnection(lpszLocalName, lpszRemoteName, _
                                       cbRemoteName)
    Select Case lngReturn
        Case ERROR_BAD_DEVICE
            Msg = "Error: Bad Device"
        Case ERROR_CONNECTION_UNAVAIL
            Msg = "Error: Connection Un-Available"
        Case ERROR_EXTENDED_ERROR
            Msg = "Error: Extended Error"
        Case ERROR_MORE_DATA
               Msg = "Error: More Data"
        Case ERROR_NOT_SUPPORTED
               Msg = "Error: Feature not Supported"
        Case ERROR_NO_NET_OR_BAD_PATH
               Msg = "Error: No Network Available or Bad Path"


        Case ERROR_NO_NETWORK

               Msg = "Error: No Network Available"
        Case ERROR_NOT_CONNECTED
               Msg = "Error: Not Connected"
        Case NO_ERROR
               ' all is successful...
    End Select
    If Len(Msg) Then
        MsgBox Msg, vbInformation
    Else
        fGetUNCPath = Left$(lpszRemoteName, cbRemoteName)
    End If
fGetUNCPath_End:
    Exit Function
fGetUNCPath_Err:
    MsgBox Err.Description, vbInformation
    Resume fGetUNCPath_End
End Function


Private Function fDriveType(strDriveName As String) As String
    Dim lngRet As Long
    Dim strDrive As String
    lngRet = GetDriveType(strDriveName)
    Select Case lngRet
        Case DRIVE_UNKNOWN 'The drive type cannot be determined.
            strDrive = "Unknown Drive Type"
        Case DRIVE_ABSENT 'The root directory does not exist.
            strDrive = "Drive does not exist"
        Case DRIVE_REMOVABLE 'The drive can be removed from the drive.
            strDrive = "Removable Media"
        Case DRIVE_FIXED 'The disk cannot be removed from the drive.
            strDrive = "Fixed Drive"
        Case DRIVE_REMOTE  'The drive is a remote (network) drive.
            strDrive = "Network Drive"
        Case DRIVE_CDROM 'The drive is a CD-ROM drive.
            strDrive = "CD Rom"
        Case DRIVE_RAMDISK 'The drive is a RAM disk.
            strDrive = "Ram Disk"
    End Select
    fDriveType = strDrive
End Function


Sub sListAllDrives()
    Dim strAllDrives As String
    Dim strTmp As String
    
    strAllDrives = fGetDrives
    If strAllDrives <> "" Then
        Do
            strTmp = Mid$(strAllDrives, 1, InStr(strAllDrives, vbNullChar) - 1)
            strAllDrives = Mid$(strAllDrives, InStr(strAllDrives, vbNullChar) + 1)
            Select Case fDriveType(strTmp)
                Case "Removable Media":
                    Debug.Print "Removable drive : " & strTmp
                Case "CD Rom":
                    Debug.Print " CD Rom drive : " & strTmp
                Case "Fixed Drive":
                    Debug.Print " Local drive : " & strTmp
                Case "Network Drive":
                    Debug.Print " Network drive : " & strTmp
                    Debug.Print " UNC Path : " & _
                                fGetUNCPath(Left$(strTmp, Len(strTmp) - 1))
            End Select
        Loop While strAllDrives <> ""
    End If
End Sub


Private Sub Form_Load()
    Debug.Print "All available drives: "
    sListAllDrives
End Sub

The VB Program is really quite long compared to its counterpart which I created with the help of the function definition by Alyce, and the resources show above. This program will simply enumerate the drives present on your PC. If any are connected to a network storage unit then the UNC path for that will be returned. Have fun with this one. Use it as you like. As the terms of use say: "use freely - do not claim what is not yours - give credit where credit is due - do good to all..."

Here is the program:

'port of a program to list all drives
'ported by Brad Moore
'some routines by Alyce Watson
'original by Alexey (alexeyka2001@rambler.ru)
'original author retains rights
'open source - use freely - do not claim what is not yours
'            - give credit where credit is due - do good to all...
    
    strAllDrives$ = fGetDrives$()
    If strAllDrives$ <> "" Then
        driveName$ = "?"
        while driveName$ <> ""
           index = index + 1
           driveName$ = word$(strAllDrives$, index)
           if len(driveName$) > 0 then
              drivetype = GetDriveType(driveName$)
              select case drivetype
                 case 0 
                    print "Unknown Drive Type : ";driveName$
                 case 1
                    print "Absent Drive : ";driveName$
                 case 2
                    print "Removable Drive : ";driveName$
                 case 3
                    print "Fixed Logical Drive : ";driveName$
                 case 4
                    print "Network Drive : ";driveName$
                    'get the UNC for the drive                    
                    print "UNC Path : ";fGetUNCPath$(driveName$)
                 case 5
                    print "CD Rom Drive : ";driveName$
                 case 6 
                    print "RAMDisk Drive : ";driveName$
              end select
           end if
        wend
    end if
    
    input "Press ENTER to quit...";a$
    end
    
    
'-----------------------------------------------------------------------
' the functions that support the code

Function GetDriveType(dir$)
    'print GetDriveType("c:\")
    CallDLL #kernel32, "GetDriveTypeA",dir$ As Ptr,GetDriveType As Long
    ' dType = 0 (No Drive)
    ' dType = 1 (Unknown Drive Type)
    ' dType = 2 (Floppy Drive)
    ' dType = 3 (Hard Drive)
    ' dType = 4 (Remote Drive)
    ' dType = 5 (CDROM)
    ' dType = 6 (RAMDISK)
End Function


Function fGetDrives$()
    'Returns all mapped drives in a string buffer

    'create a buffer of 255 characters
    strDrives$ = space$(255) + chr$(0)
    lngTmp = Len(strDrives$)
    
    calldll #kernal32, "GetLogicalDriveStringsA", _
                       lngTmp as long, _
                       strDrives$ as ptr, _
                       result as long
    
    fGetDrives$ = Left$(strDrives$, result)
End Function



function fGetUNCPath$(strDriveLetter$)
    'returns the network UNC name for the mapped drive letter
    
    'need a struct for the lenght argument so that it can be modified    
    struct RemoteNameLen, len as long
    lpszLocalName$ = strDriveLetter$ + chr$(0)
    'buffer to retunr the unc name
    lpszRemoteName$ = space$(255) + chr$(0)
    RemoteNameLen.len.struct = Len(lpszRemoteName$)
    
    open "mpr.dll" for dll as #mpr  
    calldll #mpr, "WNetGetConnectionA", _
                  lpszLocalName as ptr, _
                  lpszRemoteName as ptr, _
                  RemoteNameLen as struct, _
                  result as long
                  
    close #mpr
    
    Select Case result
        Case 4608
               Msg$ = "Error: Bad Device"
        Case 4609
               Msg$ = "Error: Connection Un-Available"
        Case 4616
               Msg$ = "Error: Extended Error"
        Case 564
               Msg$ = "Error: More Data"
        Case 80
               Msg$ = "Error: Feature not Supported"
        Case 4611
               Msg$ = "Error: No Network Available or Bad Path"
        Case 4642
               Msg$ = "Error: No Network Available"
        Case 8784
               Msg$ = "Error: Not Connected"
        Case 0
               remoteLen = RemoteNameLen.len.struct
               Msg$ = Left$(lpszRemoteName, remoteLen)
        Case else
               Msg$ = "Unknown condition on return: " + str$(result)
    End Select
    fGetUNCPath$ = Msg$
    
   'returns errors for UNC Path explained:
   'ERROR_BAD_DEVICE = 4608
   'ERROR_CONNECTION_UNAVAIL = 4609
   'ERROR_EXTENDED_ERROR = 4616
   'ERROR_MORE_DATA = 564
   'ERROR_NOT_SUPPORTED = 80
   'ERROR_NO_NET_OR_BAD_PATH = 4611
   'ERROR_NO_NETWORK = 4642
   'ERROR_NOT_CONNECTED = 8784
   'NO_ERROR = 0
   
end function


Home

Tip Corner

Plot 3d

Memory Mapped File

Random File Selector

Notes for Beginners

No SoundBlaster Board

PrintInstalled Fonts

Essential Libby

API Drive Info

Begginer Series 6

Newsletter help

Index